;Programmable [LCD 2x16 (4 bit)] /* 4-BIT OPERATION The modules will operate from a 4-bit wide data bus. Data is transferred over data lines D7-D4. D3-D0 may float. 8-bit hex code is sent one nibble at a time, with the most significant nibble sent first. The function set in the initialization routine must change to accommodate this mode. A recommended initialization routine is as follows: 8-bit 2 line display with 5x7 font: 38, 38, 06, OE, 01 (hex) 4-bit 2 line display with 5x7 font: 2, 8, 2, 8, 0, 6, 0, E, 0, 1(hex) */ /*------------------------------------------------------------------------ -******************* (Internal EEPROM Data Memory) *********************- ------------------------------------------------------------------------- The ATmega16 Contains -(512 bytes)- of Data EEPROM Memory -----------------------------------------------------------------------*/ .NOLIST ;Disable listfile generation(Combination) .include "m16def.inc" ;Read source from another file .LIST ;Reenable listfile generation on ;......................................................................... ;.......................... define ports in/out .......................... ;......................................................................... ; PortB ------------------------------------------------------------------ .equ DataOut =PORTB ;Output and Pull-Up-PortB Output= Data .equ DataDdr =DDRB ;Data direction register of the PortB ; PortB LCD - Output ----------------------------------------------------- .equ LCD_RS =0 ;bit in I/O register PORTB.0 .equ LCD_E =1 ;bit in I/O register PORTB.1 ;------------------------------------------------------------------------- ;-************* ( Define Register Local Pointer Variable ) **************- ;------------------------------------------------------------------------- .def SegMemory_1 =R7 ;define a storage for 7Segment_Memory_1 .def SegMemory_2 =R8 ;define a storage for 7Segment_Memory_2 .def SegMemory_3 =R9 ;define a storage for 7Segment_Memory_3 .def SegMemory_4 =R10;define a storage for 7Segment_Memory_4 .def Var=R16 ;define a storage for variable .def Temp1 =R17 ;define a storage for Temporary 1 .def Temp2 =R18 ;define a storage for Temporary 2 .def Memory_Data =R19;define a storage for Memory_Data .def Data_Addres =R22;define a storage for Data_Addres .def TWI_Memory =R23 ;define a storage for TWI_Memory .def XL =R26 ;define a storage for XL .def XH =R27 ;define a storage for XH .def YL =R28 ;define a storage for YL .def YH =R29 ;define a storage for YH .def ZL =R30 ;define a storage for ZL .def ZH =R31 ;define a storage for ZH /* X = R26..R27 used for calculation purposes XL= R26 XH=R27 Y = R28..R29: free YL= R28 YH=R29 Z = R30..R31 used for LPM and calculation purposes ZL= R30 ZH=R31 */ ;---------------------------**** START ****------------------------------- START: .ORG 0000 ;---------------------------**** MACRO ****------------------------------- .LISTMAC .MACRO Stack Pointer ;Define an macro [Stack Pointer] LDI Var,0x00 ;Load Immediate register R16-00 hex OUT SPL,Var ;Stack Pointer Low 00 hex LDI Var,0x01 ;Load Immediate register R16-01 hex OUT SPH,Var ;Stack Pointer High 01 hex .ENDMACRO ;End macro definition ;Delay_500ns .MACRO Delay_500ns ;Define an macro [Delay_500ns] NOP ; 8Mhz / 8 = 1us -> 100 ns NOP ; 8Mhz / 8 = 1us -> 100 ns .ENDMACRO ;------------------------------------------------------------------------- ;-**************** (Program Subroutine [ADC_Voltmeter] ) ****************- ;------------------------------------------------------------------------- Main: CLR R0 ;Load Immediate register R0 =00 hex CLR R1 ;Load Immediate register R1 =00 hex CLR R2 ;Load Immediate register R2 =00 hex CLR R3 ;Load Immediate register R3 =00 hex CLR R4 ;Load Immediate register R4 =00 hex CLR R5 ;Load Immediate register R5 =00 hex CLR R6 ;Load Immediate register R6 =00 hex CLR SegMemory_1 ;Load Immediate register R7 =00 hex CLR SegMemory_2 ;Load Immediate register R8 =00 hex CLR SegMemory_3 ;Load Immediate register R9 =00 hex CLR SegMemory_4 ;Load Immediate register R10 =00 hex CLR Var ;Load Immediate register R16 =00 hex CLR Temp1 ;Load Immediate register R17 =00 hex CLR Temp2 ;Load Immediate register R18 =00 hex CLR Memory_Data ;Load Immediate register R19 =00 hex CLR Data_Addres ;Load Immediate register R22 =00 hex CLR TWI_Memory ;Load Immediate register R23 =00 hex LDI Var,0xFF ;Load Immediate register R16=FF hex OUT DataDdr,Var ;Make DDRB For Output= FF hex CBI PORTB,LCD_RS ;Clear bit in I/O register PORTB.0 CBI PORTB,LCD_E ;Clear bit in I/O register PORTB.1 /*------------------------------------------------------------------------ -*************** (Program Subroutine LCD 2x16 (4 bit)) *****************- ------------------------------------------------------------------------- Subroutine [LCD 2x16 (4 bit)] -----------------------------------------------------------------------*/ Stack Pointer ;Call macro, show [Stack Pointer] RCALL Initialize_LCD ;Call Subroutine Initialize_LCD RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Function Set to 4 Bit_Init LCD 2lines 5*7 Matrix LDI Memory_Data,0x28;Load Immediate register R19=08 hex RCALL Send_Command ;Call Subroutine Send_Command RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Clears Display and returns cursor to the Home Position LDI Memory_Data,0x01;Load Immediate register R19=01 hex RCALL Send_Command ;Call Subroutine Send_Command RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Display On Cursor LCD ( | ) LDI Memory_Data,0x0E;Load Immediate register R19=0E hex RCALL Send_Command ;Call Subroutine Send_Command RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Command cursor shift >> right LDI Memory_Data,0x06;Load Immediate register R19=06 hex RCALL Send_Command ;Call Subroutine Send_Command RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Command Cursor to ( Line 1 ) pos1 LDI Memory_Data,0x80;Load Immediate register R19=80 hex RCALL Send_Command ;Call Subroutine Send_Command RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Display Word H LDI Memory_Data,'H' ;Load Immediate register Word RCALL Send_Data ;Call Subroutine Send_Data RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Command cursor shift >> right LDI Memory_Data,0x06;Load Immediate register R19=06 hex RCALL Send_Command ;Call Subroutine Send_Command RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Display Word e LDI Memory_Data,'e' ;Load Immediate register Word RCALL Send_Data ;Call Subroutine Send_Data RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Command cursor shift >> right LDI Memory_Data,0x06;Load Immediate register R19=06 hex RCALL Send_Command ;Call Subroutine Send_Command RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Display Word l LDI Memory_Data,'l' ;Load Immediate register Word RCALL Send_Data ;Call Subroutine Send_Data RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Command cursor shift >> right LDI Memory_Data,0x06;Load Immediate register R19=06 hex RCALL Send_Command ;Call Subroutine Send_Command RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Display Word l LDI Memory_Data,'l' ;Load Immediate register Word RCALL Send_Data ;Call Subroutine Send_Data RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Command cursor shift >> right LDI Memory_Data,0x06;Load Immediate register R19=06 hex RCALL Send_Command ;Call Subroutine Send_Command RCALL Delay_5ms ;Call Subroutine Delay_5ms ; Description: Display Word o LDI Memory_Data,'o' ;Load Immediate register Word RCALL Send_Data ;Call Subroutine Send_Data RCALL Delay_5ms ;Call Subroutine Delay_5ms STOP: RJMP STOP /*------------------------------------------------------------------------ -****************** (Subroutine Send Command Nibble) *******************- ------------------------------------------------------------------------- Subroutine Send Command Nibble |MSB| |LSB| 38 => 3 Send - 8 Send 38*F0= 3,0 38*0F= 0,8 SWAP >> 8,0 -----------------------------------------------------------------------*/ Send_Command: LDI Temp1,0b11110000 ;Load Immediate register R17 = F0 hex AND Temp1,Memory_Data ;Logical AND Registers R17 * R19 MOV Var,Temp1 ;Load Immediate register R16 <= R17 MSB LDI ZH,HIGH(Back_C_MSB);Load high of byte address intoR31 LDI ZL,LOW(Back_C_MSB) ;Load low of byte address intoR30 JMP Command_LCD ;Relative Jump to Command_LCD Back_C_MSB: LDI Temp1,0b00001111 ;Load Immediate register R17 = 0F hex AND Temp1,Memory_Data ;Logical AND Registers R17 * R19 SWAP Temp1 ;Swap Nibbles R17 |LSB| |MSB| MOV Var,Temp1 ;Load Immediate register R16 <= R17 LSB LDI ZH,HIGH(Back_C_LSB);Load high of byte address intoR31 LDI ZL,LOW(Back_C_LSB) ;Load low of byte address intoR30 JMP Command_LCD ;Relative Jump to Command_LCD Back_C_LSB: RET ;Subroutine Return C->4 /*------------------------------------------------------------------------ -******************* (Subroutine Send Data Nibble) *********************- ------------------------------------------------------------------------- Subroutine Send Data Nibble |MSB| |LSB| 41 => 4 Send - 1 Send 41*F0= 4,0 41*0F= 0,1 SWAP >> 1,0 -----------------------------------------------------------------------*/ Send_Data: LDI Temp1,0b11110000 ;Load Immediate register R17 = F0 hex AND Temp1,Memory_Data ;Logical AND Registers R17 * R19 MOV Var,Temp1 ;Load Immediate register R16 <= R17 MSB LDI ZH,HIGH(Back_D_MSB);Load high of byte address intoR31 LDI ZL,LOW(Back_D_MSB) ;Load low of byte address intoR30 JMP Data_LCD ;Relative Jump to Data_LCD Back_D_MSB: LDI Temp1,0b00001111 ;Load Immediate register R17 = 0F hex AND Temp1,Memory_Data ;Logical AND Registers R17 * R19 SWAP Temp1 ;Swap Nibbles R17 |LSB| |MSB| MOV Var,Temp1 ;Load Immediate register R16 <= R17 LSB LDI ZH,HIGH(Back_D_LSB);Load high of byte address intoR31 LDI ZL,LOW(Back_D_LSB) ;Load low of byte address intoR30 JMP Data_LCD ;Relative Jump to Data_LCD Back_D_LSB: RET ;Subroutine Return C->4 /*------------------------------------------------------------------------ -********************** ( Send Command to LCD ) ************************- ------------------------------------------------------------------------- Subroutine Send Command to LCD Comment: 1- Pin RS = 0 2- Data Command => PORTB Output ___ ___ 3- Puls E = 1/0 E ___/ \___/ \___ -----------------------------------------------------------------------*/ Command_LCD: OUT DataOut,Var ;Make PORTB For Output <- R16 CBI PORTB,LCD_RS ;Clear bit in I/O register PORTB.0 NOP Delay_500ns SBI PORTB,LCD_E ;Set bit in I/O register PORTB.1 Delay_500ns CBI PORTB,LCD_E ;Clear bit in I/O register PORTB.1 IJMP ;Indirect Jump to (Z) >> R30-R31 /*------------------------------------------------------------------------ -************************ ( Send Data to LCD ) *************************- ------------------------------------------------------------------------- Subroutine Send Data to LCD Comment: 1- Pin RS = 1 2- Data => PORTB Output ___ ___ 3- Puls E = 1/0 E ___/ \___/ \___ -----------------------------------------------------------------------*/ Data_LCD: OUT DataOut,Var ;Make PORTB For Output <- R16 SBI PORTB,LCD_RS ;Set bit in I/O register PORTB.0 NOP Delay_500ns SBI PORTB,LCD_E ;Set bit in I/O register PORTB.1 Delay_500ns CBI PORTB,LCD_E ;Clear bit in I/O register PORTB.1 IJMP ;Indirect Jump to (Z) >> R30-R31 /*------------------------------------------------------------------------ -******************* ( Subroutine Initialize LCD) **********************- ------------------------------------------------------------------------- Subroutine Initialize LCD Comment: Initialize LCD before send any data to it 1-Data => DDRB Output 1111 00 1 1 DataOut LCD_E LCD_RS 2-Initialize LCD before send [LCD_4bit] X X X X 0 1 0 0 D0 , D1 , D2 , D3 , D4 , D5 , D6 , D7 -----------------------------------------------------------------------*/ Initialize_LCD: LDI Temp1,0b11110011;Load Immediate register R17=F3 hex OUT DataDdr,Temp1 ;Make DDRB For Output= F3 hex CBI PORTB,LCD_RS ;Clear bit in I/O register PORTB.0 NOP LDI Temp1,0b00100000;Load Immediate register R17=20 hex OUT DataOut,Temp1 ;Make PORTB For Output <- R17 [LCD_4bit] Delay_500ns SBI PORTB,LCD_E ;Set bit in I/O register PORTB.1 Delay_500ns CBI PORTB,LCD_E ;Clear bit in I/O register PORTB.1 RET ;Subroutine Return /*------------------------------------------------------------------------ -************************ (Give Some Time 5ms) *************************- ------------------------------------------------------------------------- Time reference Give Some Time 5ms Comment: TCCR0 = 0000 0011 ClkI/O/64 (From prescaler) 8MHz / 64 = 0.125MHz T = 1/0.125MHz = 8 us Clocks => 1+1+1+1+1+0+2+1+1+4+3 = 16 => 8Mhz / 8 = 1us => 16us T+Clocks = 8+16 = 24us Delay 5.376ms = 5.376ms/24us >> 5376ms/24 = 224 ~= 224 TCNT0 = ? >>> 256-224 = 32 >>> hex >>>20 -----------------------------------------------------------------------*/ Delay_5ms: LDI Temp1,0x03 ;Load Immediate register R17=03 hex C->1 OUT TCCR0,Temp1 ;Timer/Counter0 Control Frequency=64 C->1 LDI Temp2,0x20 ;Load Immediate register R18=20 hex C->1 OUT TCNT0,Temp2 ;Timer/Counter(8 Bits)=EC hex C->1 ;TCCR0=010 ClkI/O/8 (From prescaler) Loop_5ms: IN Var,TIFR ;Timer/Counter Interrupt FlagRegister C->1 SBRS Var,TOV0 ;Skip if Bit in Registeris Set TOV0=1 C->0 RJMP Loop_5ms ;Jump to 1ms C->2 LDI Var,0xFF ;Load Immediate register R16=FF hex C->1 OUT TIFR,Var ;Clear Interrupt FlagRegister C->1 RET ;Subroutine Return C->4